/////////////////////////////////////////////////////////////////////////////
// Name:        ax_menu_choice.cpp
// Purpose:     Modal choice menu class
// Author:      Julian Smart
// Modified by:
// Created:     2009-03-20
// RCS-ID:
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#include "wx/wx.h"

#include "ax/ax_menu_choice.h"
#include "ax/ax_validator.h"

IMPLEMENT_CLASS( AxModalChoiceMenu, AxModalMenu )

AxModalChoiceMenu::AxModalChoiceMenu(AxMenuController* controller, AxMenuItem* item,
        const wxString& menuLabel,
        const wxString& description,
        const wxArrayString& labels,
        const wxArrayString& ids,
        const wxArrayString& descriptions,
        const wxString& defaultId):
    AxModalMenu(controller, item)
{
    Init();

    AxMenu* menu = new AxMenu;
    menu->SetLabel(menuLabel);
    menu->SetDescription(description);

    wxASSERT(labels.GetCount() == ids.GetCount());
    wxASSERT(labels.GetCount() == descriptions.GetCount());

    size_t i;
    for (i = 0; i < labels.GetCount(); i++)
    {
        wxString label = labels[i];
        wxString id = ids[i];
        wxString descr = descriptions[i];

        AxMenuItem* child = new AxMenuItem(label, descr, id,
            new AxChoiceMenuActivator(this));
        child->GetActivator()->SetMenuItem(child);
        menu->AddItem(child);

        if (defaultId == id)
            menu->SetCurrentSelection(i);
    }
    AxMenuItem* child = new AxMenuItem(_("Cancel"), _("Cancel this choice."), AxIdentifierCancel,
        new AxChoiceMenuActivator(this));
    child->GetActivator()->SetMenuItem(child);
    child->SetStyle(AxMenuStyleBold);
    menu->AddItem(child);

    SetMenu(menu);
}

/*
 * AxChoiceMenuActivator implementation.
 * Ends the modal menu when the item is activated.
 */

IMPLEMENT_DYNAMIC_CLASS( AxChoiceMenuActivator, AxActivator )

void AxChoiceMenuActivator::Copy(const AxChoiceMenuActivator& activator)
{
    AxActivator::Copy(activator);
    m_choiceMenu = activator.m_choiceMenu;
}

AxMenu* AxChoiceMenuActivator::Activate(AxMenuController* WXUNUSED(controller), AxMenuItem* item)
{
    if (m_choiceMenu)
        m_choiceMenu->EndModal(item->GetId());
    return NULL;
}

/*
 * AxChoiceActivator implementation.
 * Sets the value of a string variable when selected.
 */

IMPLEMENT_DYNAMIC_CLASS( AxChoiceActivator, AxAutoUpdateActivator )

AxChoiceActivator::AxChoiceActivator(
                  const wxString& labelSpec,
                  const wxString& descriptionSpec):
  AxAutoUpdateActivator(labelSpec, descriptionSpec)
{
    Init();
}

void AxChoiceActivator::Init()
{
}

AxChoiceMenuItem* AxChoiceActivator::GetChoiceMenuItem() const
{
    return wxDynamicCast(GetMenuItem(), AxChoiceMenuItem);
}

void AxChoiceActivator::Copy(const AxChoiceActivator& activator)
{
    AxAutoUpdateActivator::Copy(activator);
}

AxMenu* AxChoiceActivator::Activate(AxMenuController* controller, AxMenuItem* item)
{
    AxChoiceMenuItem* choiceItem = GetChoiceMenuItem();
    if (!choiceItem)
        return NULL;

    wxString defaultId = choiceItem->GetSelectionId();

    AxModalChoiceMenu menu(controller, item,
        _("Choice"),
        _("Please choose a value from this list."),
        choiceItem->GetLabels(), choiceItem->GetIds(), choiceItem->GetDescriptions(),
        defaultId);

    wxString id = menu.ShowModal();

    {
        if (id != AxIdentifierCancel)
        {
            int idx = choiceItem->GetIds().Index(id);
            if (idx != -1)
            {
                choiceItem->SetSelection(idx);
                if (item->GetValidator())
                    item->GetValidator()->TransferDataFromMenu();

                UpdateItem(controller, item);

                wxString result = choiceItem->GetSelectionLabel();

                if (!item->GetId().IsEmpty())
                {
                    wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, AxGetId(item->GetId()));
                    event.SetInt(idx);
                    event.SetString(result);
                    event.SetEventObject(item);

                    item->ProcessEvent(event);
                }
            }
        }
    }

    return NULL;
}

wxString AxChoiceActivator::CreateString(const wxString& spec, bool isLabel)
{
    AxChoiceMenuItem* choiceItem = GetChoiceMenuItem();
    if (choiceItem)
        return choiceItem->CreateString(spec, isLabel);
    else
        return spec;
}

/*
 * AxChoiceMenuItem class implementation.
 */

IMPLEMENT_DYNAMIC_CLASS( AxChoiceMenuItem, AxMenuItem )

AxChoiceMenuItem::AxChoiceMenuItem(const wxString& label, const wxString& description,
        const wxString& id,
        const wxArrayString& labels,
        const wxArrayString& ids,
        const wxArrayString& descriptions,
        //wxString* stringPtr,
        int selection)
{
    Create(label, description, id, labels, ids, descriptions, selection);
}

bool AxChoiceMenuItem::Create(const wxString& label, const wxString& description,
        const wxString& id,
        const wxArrayString& labels,
        const wxArrayString& ids,
        const wxArrayString& descriptions,
        //wxString* stringPtr,
        int selection)
{
    SetLabel(label);
    SetKind(_("choice"));
    SetDescription(description);
    SetId(id);
    SetDynamic();

    m_labels = labels;
    m_ids = ids;
    m_descriptions = descriptions;
    //m_stringPtr = stringPtr;

    m_selection = selection;
    AxChoiceActivator* activator = new AxChoiceActivator(label, description);
    SetActivator(activator);

    return true;
}

void AxChoiceMenuItem::Init()
{
    m_selection = 0;
}

void AxChoiceMenuItem::Copy(const AxChoiceMenuItem& item)
{
    AxMenuItem::Copy(item);

    m_labels = item.m_labels;
    m_ids = item.m_ids;
    m_descriptions = item.m_descriptions;
    m_selection = item.m_selection;
}

// Set current selection
void AxChoiceMenuItem::SetSelection(int i)
{
    m_selection = i;
}

// Get current selected label
wxString AxChoiceMenuItem::GetSelectionLabel() const
{
    if (m_selection != -1 && m_selection < (int) m_labels.GetCount())
    {
        return m_labels[m_selection];
    }
    return wxEmptyString;
}

/// Get current selected id
wxString AxChoiceMenuItem::GetSelectionId() const
{
    if (m_selection != -1 && m_selection < (int) m_ids.GetCount())
    {
        return m_ids[m_selection];
    }
    return wxEmptyString;
}

// Set current selection
void AxChoiceMenuItem::SetSelectionByLabel(const wxString& label)
{
    int pos = m_labels.Index(label);
    if (pos != -1)
        m_selection = pos;
}

// Set current selection
void AxChoiceMenuItem::SetSelectionById(const wxString& id)
{
    int pos = m_ids.Index(id);
    if (pos != -1)
        m_selection = pos;
}

wxString AxChoiceMenuItem::CreateString(const wxString& spec, bool WXUNUSED(isLabel))
{
    wxString value;
    if (m_selection != -1 && m_selection < (int) m_labels.GetCount())
        value = m_labels[m_selection];

    if (value.IsEmpty())
        value = _("none");
    wxString str = spec;
    str.Replace(wxT("%VALUE%"), value);
    return str;
}

IMPLEMENT_DYNAMIC_CLASS( AxChoiceValidator, AxValidator )

// Override to pass a value from the UI to a data structure
bool AxChoiceValidator::TransferDataFromMenu()
{
    AxChoiceMenuItem* choiceItem = wxDynamicCast(GetMenuItem(), AxChoiceMenuItem);
    if (choiceItem)
    {
        if (m_stringPtr)
            * m_stringPtr = choiceItem->GetSelectionLabel();
    }

    return true;
}

// Override to pass a value from a data structure to the UI
bool AxChoiceValidator::TransferDataToMenu()
{
    AxChoiceMenuItem* choiceItem = wxDynamicCast(GetMenuItem(), AxChoiceMenuItem);
    if (choiceItem)
    {
        if (m_stringPtr)
            choiceItem->SetSelectionByLabel(* m_stringPtr);
    }

    return true;
}

